package auctionhaus

import org.springframework.dao.DataIntegrityViolationException
import grails.converters.JSON

class ListingController {

    static allowedMethods = [save: "POST", update: "POST", delete: "POST"]
    def listingService

    def index() {
        redirect(action: "list", params: params)
    }

    def list() {
        if (!params.sort)
        {
            params.sort='dateCreated'
            params.order='desc'
        }
        params.max = 5
        [listingInstanceList: Listing.openListings.list(params), listingInstanceTotal: Listing.openListings.list().size()]
    }

    def myList() {
        if (!params.sort)
        {
            params.sort='dateCreated'
            params.order='desc'
        }
        params.max = 5
        Customer c = Customer.findById(session.customer.id);
        def query = Listing.where{
            seller.id == session.customer.id
        }
        render(view: "list", model: [listingInstanceList: query.list(params), listingInstanceTotal: query.list(), myList: true])
    }

    def create() {
        [listingInstance: new Listing(params)]
    }

    def save() {
        def listingInstance = new Listing(params)
        def newListing = listingService.createListing(listingInstance)

        if (newListing == "Unsuccessfull") {
            render(view: "create", model: [listingInstance: listingInstance])
            return
        }

        flash.message = message(code: 'default.created.message', args: [message(code: 'listing.label', default: 'Listing'), newListing.id])
        redirect(action: "show", id: newListing.id)
    }

    def show() {
        def listingInstance = Listing.get(params.id)
        if (!listingInstance) {
            flash.message = message(code: 'default.not.found.message', args: [message(code: 'listing.label', default: 'Listing'), params.id])
            redirect(action: "list")
            return
        }
        def bid = listingInstance.bids.max {it.amount}
        [listingInstance: listingInstance, lastBid: bid]
    }

    def placeBid() {

        def listingInstance = Listing.get(params.id)
        if (!listingInstance) {
            flash.message = message(code: 'default.not.found.message', args: [message(code: 'listing.label', default: 'Listing'), params.id])
            redirect(action: "list")
            return
        }
        def bidAmount
        try
        {
            bidAmount = Double.parseDouble(params.amount)
        }
        catch (NumberFormatException nfe)
        {
            def jsonMap = [amount: null, listingId: params.id, error: true, message: "Must enter a valid price."]
            render jsonMap as JSON
            return
        }
        Bid bid = new Bid(bidder: session.customer, listing: listingInstance, amount: params.amount)
        def bidMap = listingService.placeBid(bid)

        def jsonMap = [amount: bidMap.bid?.amount, listingId: params.id, error: bidMap.hasErrors, message: bidMap.message]
        render jsonMap as JSON
    }

    def getLatestBids()
    {
        def listingInstance = Listing.get(params.id)
        if (!listingInstance) {
            message = message(code: 'default.not.found.message', args: [message(code: 'listing.label', default: 'Listing'), params.id])
        }
        def bids = Bid.forListing(listingInstance).list(sort: 'dateCreated', order: 'desc')
        if (bids.size() > 0)
        {
            def first10 = bids.take(bids.size() > 10 ? 10 : bids.size())
            HashMap jsonMap = new HashMap()
            jsonMap.bids = first10.collect {bid ->
                return [id: bid.id, bidder: bid.bidder.emailAddress.replaceFirst(/@.*/, ""), dateCreated: bid.dateCreated.getDateTimeString(), amount: bid.amount]
            }
            def x = jsonMap as JSON
            render x
        }
        else
        {
            render null
        }

    }

    def isExpired() {

        def listingInstance = Listing.get(params.id)
        def message = null;
        def expired = false;
        if (!listingInstance) {
            message = message(code: 'default.not.found.message', args: [message(code: 'listing.label', default: 'Listing'), params.id])
        }
        else
        {
            expired = listingInstance.endDateTime.before(new Date())
        }
        def jsonMap = [id: listingInstance.id, expired: expired, message: message]
        render jsonMap as JSON
    }

    def edit() {
        def listingInstance = Listing.get(params.id)
        if (!listingInstance) {
            flash.message = message(code: 'default.not.found.message', args: [message(code: 'listing.label', default: 'Listing'), params.id])
            redirect(action: "list")
            return
        }

        [listingInstance: listingInstance]
    }

    def update() {
        def listingInstance = Listing.get(params.id)
        if (!listingInstance) {
            flash.message = message(code: 'default.not.found.message', args: [message(code: 'listing.label', default: 'Listing'), params.id])
            redirect(action: "list")
            return
        }

        if (params.version) {
            def version = params.version.toLong()
            if (listingInstance.version > version) {
                listingInstance.errors.rejectValue("version", "default.optimistic.locking.failure",
                        [message(code: 'listing.label', default: 'Listing')] as Object[],
                        "Another user has updated this Listing while you were editing")
                render(view: "edit", model: [listingInstance: listingInstance])
                return
            }
        }

        listingInstance.properties = params

        if (!listingInstance.save(flush: true)) {
            render(view: "edit", model: [listingInstance: listingInstance])
            return
        }

        flash.message = message(code: 'default.updated.message', args: [message(code: 'listing.label', default: 'Listing'), listingInstance.id])
        redirect(action: "show", id: listingInstance.id)
    }

    def delete() {
        def listingInstance = Listing.get(params.id)
        if (!listingInstance) {
            flash.message = message(code: 'default.not.found.message', args: [message(code: 'listing.label', default: 'Listing'), params.id])
            redirect(action: "list")
            return
        }

        try {
            listingInstance.delete(flush: true)
            flash.message = message(code: 'default.deleted.message', args: [message(code: 'listing.label', default: 'Listing'), params.id])
            redirect(action: "list")
        }
        catch (DataIntegrityViolationException e) {
            flash.message = message(code: 'default.not.deleted.message', args: [message(code: 'listing.label', default: 'Listing'), params.id])
            redirect(action: "show", id: params.id)
        }
    }
}
